#pragma once

#include <algorithm>
#include <hash_map>
#include <vector>
#include "Follow.h"


using namespace stdext;
using namespace std;


bool Follow::isPresent(vector<Type::Index::Line> v, Type::Index::Line i){
	vector<Type::Index::Line>::iterator iter;
	return (std::find(v.begin(), v.end(), i) != v.end());
}
	
Follow::Follow(void) {
	Follow::followsBitMapSetFlag = false;
}

Follow::~Follow(void){
	Follow::followsBitMapSetFlag = false;
	Follow::followRelation.clear();
}

void Follow::setFollows(Type::Index::Line a,Type::Index::Line b){
	if ((followRelation.find(a) == followRelation.end())&&(followRelation.find(b) == followRelation.end())){
		Follow::followRelation[a] = b;
		Follow::revertFollowRelation[b] = a;
	}else{
		if(followRelation.find(a) != followRelation.end()){
			Type::Index::Line temp = followRelation[a];
			revertFollowRelation.erase(temp);
		}
		if(revertFollowRelation.find(b)!= followRelation.end()){
			Type::Index::Line temp = revertFollowRelation[b];
			followRelation.erase(temp);
		}
		Follow::followRelation[a] = b;
		Follow::revertFollowRelation[b] = a;
	}
}

Type::Index::Line Follow::getFollows(Type::Index::Line a){
	hash_map<Type::Index::Line,Type::Index::Line>::const_iterator hm_rcIter;
	hm_rcIter = followRelation.find(a);
	if (hm_rcIter == followRelation.end()){
		return -1;
	}else{
		return hm_rcIter->second;
	}
}
Type::Index::Line Follow::getFollowedBy(Type::Index::Line b){
	hash_map<Type::Index::Line,Type::Index::Line>::const_iterator hm_rcIter;
	hm_rcIter = revertFollowRelation.find(b);
	if (hm_rcIter == revertFollowRelation.end()){
		return -1;
	}else{
		return hm_rcIter->second;
	}
}

bool Follow::isFollows(Type::Index::Line a,Type::Index::Line b){
	if (Follow::followsBitMapSetFlag == false){
		hash_map<Type::Index::Line,Type::Index::Line>::const_iterator hm_rcIter;
		hm_rcIter = followRelation.find(a);
		if (hm_rcIter == followRelation.end()){
			return false;
		}else{
			return hm_rcIter->second == b;
		}
	}else{
		return Follow::followsBitMap.at(a).at(b);
	}
}
bool Follow::setFollowsBitMap(vector<vector<bool>> CBM){
	if (CBM.empty()){
		return Follow::followsBitMapSetFlag;
	}else{
		int colsize = CBM.size();
		int rowsize = CBM.at(0).size();
		followsBitMap.resize(colsize, vector<bool>(rowsize,false));
		for (int i=0; i<colsize;i++){
			for (int j=0; j<rowsize;j++){
				if (Follow::getFollows(i) != j && CBM.at(i).at(j)){
					return Follow::followsBitMapSetFlag;
				}
				followsBitMap.at(i).at(j) = CBM.at(i).at(j);
			}
		}
		Follow::followsBitMapSetFlag = true;
		return Follow::followsBitMapSetFlag;
	}
}
bool Follow::isBitMapSet(){
	return Follow::followsBitMapSetFlag;
}